package com.lbssoft.gpsbd.aspect;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.lbssoft.gpsbd.annotation.LogAnnotation;
import com.lbssoft.gpsbd.common.LoggerUtil;
import com.lbssoft.gpsbd.model.Log;
import com.lbssoft.gpsbd.model.LoginLog;
import com.lbssoft.gpsbd.model.vo.UserVo;
import com.lbssoft.gpsbd.service.LogService;
import com.lbssoft.gpsbd.service.RoleService;
import org.apache.shiro.SecurityUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by nczc on 2018/1/16.
 */
@Aspect
@Component
public class LogAspect {
    private final org.slf4j.Logger logger = LoggerFactory.getLogger(LogAspect.class);
    @Autowired
    private LogService logService;



    @Pointcut("@annotation(com.lbssoft.gpsbd.annotation.LogAnnotation)")
    private void pointCutMethod(){}


    /**
     * 获取返回内容
     * @param object
     */
    @AfterReturning(returning = "object",pointcut = "pointCutMethod()")
    public void doAfterReturn(JoinPoint joinPoint,Object object){
        Long start = System.currentTimeMillis();
        Log log = new Log();
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        UserVo user = (UserVo) SecurityUtils.getSubject().getPrincipal();
        if(user == null){
            logger.warn("user 信息为空");
        }else{
            log.setUserId(user.getId());
            log.setAccount(user.getAccount());

        }
        //下面开始获取 ip，targetType，remark，action
        try {
            Map<String,String> map = getLogMark(joinPoint);
            log.setAction(map.get(LoggerUtil.LOG_ACTION));
            log.setTargetType(map.get(LoggerUtil.LOG_TARGET_TYPE));
            log.setRemark(map.get(LoggerUtil.LOG_REMARK));
            log.setIp(LoggerUtil.getCliectIp(request));
            if(joinPoint.getArgs()!=null&&joinPoint.getArgs().length!=0){
                //如果是登陆动作删除密码以免暴露
                if(map.get(LoggerUtil.LOG_ACTION).equals("login")){
                    JSONObject jsonObject = JSONObject.parseObject(JSON.toJSONString(joinPoint.getArgs()[0]));
                    jsonObject.remove("password");
                    log.setParams(JSON.toJSONString(jsonObject));
                }else{
                    log.setParams(JSON.toJSONString(joinPoint.getArgs()[0]));
                }

            }

            log.setResult(JSON.toJSONString(object));
            JSONObject resultJson = JSONObject.parseObject(JSON.toJSONString(object));
            log.setStatus(resultJson.getInteger("code"));
            logService.add(log);
        }catch (ClassNotFoundException c){
            logger.error(c.getMessage());
        }catch (Exception e){
            logger.error("插入日志异常{}",e.getMessage());
        }
        Long end = System.currentTimeMillis();
        logger.info("记录日志消耗时间:"+ (end - start));
    }

    private Map<String,String> getLogMark(JoinPoint joinPoint) throws ClassNotFoundException {
        Map<String,String> map = new HashMap<>();
        String methodName = joinPoint.getSignature().getName();
        String targetName = joinPoint.getTarget().getClass().getName();
        Class targetClass = Class.forName(targetName);
        Method[] methods = targetClass.getMethods();
        for (Method method : methods){
            if(method.getName().equals(methodName)){
                LogAnnotation logAnnotation = method.getAnnotation(LogAnnotation.class);
                map.put(LoggerUtil.LOG_TARGET_TYPE,logAnnotation.targetType());
                map.put(LoggerUtil.LOG_ACTION,logAnnotation.action());
                map.put(LoggerUtil.LOG_REMARK,logAnnotation.remark());
            }
        }
        return map;
    }
}
